package au.edu.educationau.opensource.dsm;

import java.io.File;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import au.edu.educationau.opensource.dsm.cache.DiskCache;
import au.edu.educationau.opensource.dsm.service.DBConnectionService;
import au.edu.educationau.opensource.dsm.service.PropertiesService;
import au.edu.educationau.opensource.dsm.service.SOAPSearchResultCacheService;
import au.edu.educationau.opensource.dsm.service.SearchManagerService;
import au.edu.educationau.opensource.dsm.service.SearchResultService;
import au.edu.educationau.opensource.dsm.service.spell.SpellCheckService;
import au.edu.educationau.opensource.dsm.threadpool.ThreadPool;
import au.edu.educationau.opensource.dsm.util.SimpleTransform;
import au.edu.educationau.opensource.dsm.worker.AdapterGroups;
import au.edu.educationau.opensource.dsm.worker.SearchAdapterFactory;
import au.edu.educationau.opensource.dsm.worker.VocabMapper;

public class OpenDSMCore implements DSMCore {
	Logger logger = Logger.getLogger(this.getClass());

	public static final int THREAD_POOL_SIZE = 250;

	private boolean initilized = false;

	private ThreadPool _threadPool = new ThreadPool(THREAD_POOL_SIZE);
	private DiskCache _diskCache_Instance = null;
	private DBConnectionService _dbConnectionService = null;
	private SearchManagerService _searchManagerService_Instance = null;
	private SearchResultService _searchResultService_Instance = null;
	private SpellCheckService _spellCheckService_Instance = null;
	private SOAPSearchResultCacheService _sOAPSearchResultCacheService = null;

	private String APP_INSTANCE = System.getProperty("dsm.instance");

	public Object getService(String name) throws UnknownServiceException {
		if (name == null) {
			throw new NullPointerException("No service name passed");
		}

		if (!initilized) {
			throw new IllegalStateException("Not initilized");
		}

		if (THREAD_POOL.equals(name)) {
			return _threadPool;
		} else if (DISK_CACHE.equals(name)) {
			return _diskCache_Instance;
		} else if (DB_CONNECTION.equals(name)) {
			return _dbConnectionService;
		} else if (SEARCH_MANAGER.equals(name)) {
			return _searchManagerService_Instance;
		} else if (SEARCH_RESULTS.equals(name)) {
			return _searchResultService_Instance;
		} else if (SPELL_CHECK.equals(name)) {
			return _spellCheckService_Instance;
		} else if (SOAP_SEARCH.equals(name)) {
			return _sOAPSearchResultCacheService;
		} else if (additionalServiceSupported(name)) {
			return getAdditionalService(name);
		} else {
			throw new UnknownServiceException(name + " is an unknown service");
		}
	}

	protected Object getAdditionalService(String name) throws UnknownServiceException {
		// can be overridden to support additional services
		return null;
	}

	protected boolean additionalServiceSupported(String name) {
		// can be overridden to support additional services
		return false;
	}

	public void init() {
		if (null != APP_INSTANCE && APP_INSTANCE.length() > 0) {
			logger.info("Loading DSM Instance: " + APP_INSTANCE);
		} else {
			logger.info("Loading P R O D U C T I O N DSM Instance");
		}
		System.getProperties().setProperty("sun.net.client.defaultConnectTimeout", "20000");
		System.getProperties().setProperty("sun.net.client.defaultReadTimeout", "90000");

		String propertiesDir = PropertiesService.getStringProperty("dsm4_properties_dir", "./WEB-INF/etc/config/") + File.separator;
		if (null != APP_INSTANCE && APP_INSTANCE.length() > 0) {
			PropertiesService.loadProperties(propertiesDir + "dsm." + APP_INSTANCE + ".properties");
		} else {
			PropertiesService.loadProperties(propertiesDir + "dsm.properties");
		}

		// configure log4j logging
		String log4jConfigFilePath = propertiesDir + PropertiesService.getStringProperty("log4j.config.file", "log4j.properties");
		PropertyConfigurator.configure(log4jConfigFilePath);
		logger.info("Logging configured using file " + log4jConfigFilePath);

		// load xsl properties
		PropertiesService.loadProperties(propertiesDir + "xsl.properties");
		// INIT XSL Simple Transform Service
		SimpleTransform.prepareStylesheets();

		SearchAdapterFactory.init();
		AdapterGroups.init();
		VocabMapper.init(propertiesDir);

		if (PropertiesService.getBooleanProperty("database.enabled", false)) {
			if (null != APP_INSTANCE && APP_INSTANCE.length() > 0) {
				_dbConnectionService = DBConnectionService.getInstance(propertiesDir + "db." + APP_INSTANCE + ".properties");
			} else {
				_dbConnectionService = DBConnectionService.getInstance(propertiesDir + "db.properties");
			}
		}

		_diskCache_Instance = DiskCache.init();
		_searchManagerService_Instance = SearchManagerService.getInstance();
		_searchResultService_Instance = SearchResultService.getInstance();
		_sOAPSearchResultCacheService = SOAPSearchResultCacheService.getInstance();
		if(PropertiesService.getBooleanProperty("search.spellchecker", false)) {
			try {
				Class searchServiceClass = Class.forName(PropertiesService.getStringProperty("spell.searchservice","au.educationau."));
				_spellCheckService_Instance = (SpellCheckService)searchServiceClass.newInstance();
				
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		//	
		}

		initilized = true;

		logger.info("DSM Started OK using core class " + this.getClass());
	}

}
